package com.tgra;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.GL11;
import com.badlogic.gdx.graphics.Texture;

public class MazeCore implements ApplicationListener
{
	Maze maze;
	Camera cam;
	Texture sides;
	Texture floor;
	Texture goal;
	Point3D oldpos;
	Point3D newpos;
	Vector3D moveVector;
	@Override
	public void create()
	{
		Gdx.gl11.glEnable(GL11.GL_DEPTH_TEST);
		Gdx.gl11.glEnable(GL11.GL_LIGHTING);
		Gdx.gl11.glEnable(GL11.GL_LIGHT0);
		Gdx.gl11.glEnable(GL11.GL_LIGHT1);
		Gdx.gl11.glEnable(GL11.GL_DEPTH_TEST);
		Gdx.gl11.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

		Gdx.gl11.glMatrixMode(GL11.GL_PROJECTION);
		Gdx.gl11.glLoadIdentity();
		Gdx.glu.gluPerspective(Gdx.gl11, 70, 1.333333f, 0.1f, 30.0f);

		Gdx.gl11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
		sides = new Texture(Gdx.files.internal("assets/textures/redbrick.png"));
		floor = new Texture(Gdx.files.internal("assets/textures/bluebrick.png"));
		goal = new Texture(Gdx.files.internal("assets/textures/blazkowicz.png"));
		maze = new Maze(7,7,sides, floor, goal);
		maze.generate(0, 0);
		cam = new Camera(new Point3D(0.5f, 0.5f, 0.5f), new Point3D(45.0f, 0.5f, 0.0f), new Vector3D(0.0f, 1.0f, 0.0f));
		newpos = new Point3D(0,0,0);
		oldpos = new Point3D(0,0,0);
		moveVector = new Vector3D(cam.eye.x, cam.eye.y, cam.eye.z);
	}
	
	public void update()
	{
		oldpos.x = cam.eye.x;
		oldpos.z = cam.eye.z;
		float deltaTime = Gdx.graphics.getDeltaTime();

		if(Gdx.input.isKeyPressed(Input.Keys.A))
		{
			cam.yaw(-180.0f * deltaTime);
		}
		if(Gdx.input.isKeyPressed(Input.Keys.D))
		{
			cam.yaw(180.0f * deltaTime);
		}
		if(Gdx.input.isKeyPressed(Input.Keys.W))
		{
			cam.slide(0.0f, 0.0f, -1.0f * deltaTime);
		}
		if(Gdx.input.isKeyPressed(Input.Keys.S))
		{
			cam.slide(0.0f, 0.0f, 1.0f * deltaTime);
		}
		if(Gdx.input.isKeyPressed(Input.Keys.Q))
		{
			cam.slide(-1.0f * deltaTime, 0.0f, 0.0f);
		}
		if(Gdx.input.isKeyPressed(Input.Keys.E))
		{
			cam.slide(1.0f * deltaTime, 0.0f, 0.0f);
		}
		newpos.x = cam.eye.x;
		newpos.z = cam.eye.z;
		moveVector.set(newpos.x - oldpos.x,newpos.y - oldpos.y , newpos.z - oldpos.z);
		collide();
		newpos.x = cam.eye.x;
		newpos.z = cam.eye.z;
		moveVector.set(newpos.x - oldpos.x,newpos.y - oldpos.y , newpos.z - oldpos.z);
		collide();
		if(checkVictory())
		{
			cam.eye.x = 0.5f;
			cam.eye.y = 0.5f;
			cam.eye.z = 0.5f;
		}
	}
	
	public void display()
	{
		Gdx.gl11.glClear(GL11.GL_COLOR_BUFFER_BIT|GL11.GL_DEPTH_BUFFER_BIT);
		cam.setModelViewMatrix();
		
		float[] lightDiffuse = {0.0f, 0.0f, 0.0f, 1.0f};
		Gdx.gl11.glLightfv(GL11.GL_LIGHT0, GL11.GL_AMBIENT, lightDiffuse, 0);

		float[] lightPosition = {2.5f, 2.5f, 2.5f, 1.0f};
		Gdx.gl11.glLightfv(GL11.GL_LIGHT0, GL11.GL_POSITION, lightPosition, 0);

		float[] materialDiffuse = {1.0f, 1.0f, 1.0f, 1.0f};
		Gdx.gl11.glMaterialfv(GL11.GL_FRONT, GL11.GL_DIFFUSE, materialDiffuse, 0);
		
		maze.draw();
		Gdx.gl11.glDisable(GL11.GL_LIGHTING);
	}

	@Override
	public void dispose()
	{
		// TODO Auto-generated method stub
		
	}

	@Override
	public void pause()
	{
		// TODO Auto-generated method stub
		
	}

	@Override
	public void render()
	{
		display();
		update();
	}

	@Override
	public void resize(int arg0, int arg1)
	{
		// TODO Auto-generated method stub
		
	}

	@Override
	public void resume()
	{
		// TODO Auto-generated method stub
		
	}
	public void collide()
	{
		Cell currentCell = maze.cells[(int)(cam.eye.x)][(int)(cam.eye.z)];
		Cell northCell = maze.cells[(int)(cam.eye.x)][(int)(cam.eye.z+1)];
		Cell eastCell = maze.cells[(int)(cam.eye.x+1)][(int)(cam.eye.z)];
		float relativeX = cam.eye.x - (int)cam.eye.x;
		float relativeZ = cam.eye.z - (int)cam.eye.z;
		if(moveVector.x > 0)
		{
			if(eastCell.westWall)
			{
				if(relativeX > 0.75)
				{
					cam.eye.x = (int)cam.eye.x + 0.75f;
				}
			}
		}
		if(moveVector.x < 0)
		{
			if(currentCell.westWall)
			{
				if(relativeX < 0.25)
				{
					cam.eye.x = (int)cam.eye.x + 0.25f;
				}
			}
			
		}
		if(moveVector.z > 0)
		{
			if(northCell.southWall)
			{
				if(relativeZ > 0.75)
				{
					cam.eye.z = (int)cam.eye.z + 0.75f;
				}
			}
			
		}
		if(moveVector.z < 0)
		{
			if(currentCell.southWall)
			{
				if(relativeZ < 0.25)
				{
					cam.eye.z = (int)cam.eye.z + 0.25f;
				}
			}
		}
	}
	public boolean checkVictory()
	{
		if(maze.mazeWidth-1 == (int)(cam.eye.x) && maze.mazeLength-1 == (int)(cam.eye.z))
		{
			int width = maze.mazeWidth;
			int length = maze.mazeLength;
			maze = new Maze(width,length,sides,floor,goal);
			maze.generate(0,0);
			return true;
		}
		return false;
	}

}
